from abc import ABC, abstractmethod
from typing import Optional, Dict, Tuple
import random

# 卡牌类型常量
CARD_TYPE_BASIC = "basic"
CARD_TYPE_EQUIPMENT = "equipment"
CARD_TYPE_TRICK = "trick"

# 基础牌子类型
BASIC_ATTACK = "attack"
BASIC_DEFEND = "defend"
BASIC_HEAL = "heal"
BASIC_NEUTRALIZE = "neutralize"

# 装备牌子类型
EQUIP_WEAPON = "weapon"
EQUIP_ARMOR = "armor"
EQUIP_MOUNT_ATTACK = "mount_attack"
EQUIP_MOUNT_DEFEND = "mount_defend"

# 锦囊牌子类型
TRICK_INSTANT = "instant"
TRICK_DELAYED = "delayed"

# 花色常量
SUIT_HEART = "红桃"
SUIT_DIAMOND = "方片"
SUIT_CLUB = "梅花"
SUIT_SPADE = "黑桃"

class Card(ABC):
    """卡牌基类"""
    def __init__(self, card_id: int, name: str, card_type: str, subtype: str = "", suit: str = "", number: int = 0):
        self.card_id = card_id
        self.name = name
        self.card_type = card_type
        self.subtype = subtype
        self.suit = suit
        self.number = number
        self.is_used = False
    
    @abstractmethod
    def use(self, game, source, target=None) -> bool:
        """使用卡牌"""
        pass
    
    def is_red(self) -> bool:
        """判断是否为红色牌"""
        return self.suit in [SUIT_HEART, SUIT_DIAMOND]
    
    def is_black(self) -> bool:
        """判断是否为黑色牌"""
        return self.suit in [SUIT_SPADE, SUIT_CLUB]
    
    def __str__(self) -> str:
        return f"{self.name}({self.suit}{self.number})"

class BasicCard(Card):
    """基础牌"""
    def __init__(self, card_id: int, name: str, subtype: str, suit: str = "", number: int = 0):
        super().__init__(card_id, name, CARD_TYPE_BASIC, subtype, suit, number)

class AttackCard(BasicCard):
    """杀牌"""
    def __init__(self, card_id: int, suit: str = "", number: int = 0, is_fire: bool = False, is_thunder: bool = False):
        name = "火杀" if is_fire else "雷杀" if is_thunder else "杀"
        super().__init__(card_id, name, BASIC_ATTACK, suit, number)
        self.is_fire = is_fire
        self.is_thunder = is_thunder
        self.damage = 1
    
    def use(self, game, source, target) -> bool:
        """使用杀牌攻击目标"""
        if not self._can_attack(source, target):
            return False
        
        # 询问目标是否出闪
        # 这里会与GUI交互
        
        # 如果目标没有出闪，造成伤害
        damage = self.damage
        if source.has_drunk:
            damage += 1
            source.has_drunk = False
        
        target.take_damage(damage, source, self.is_fire, self.is_thunder)
        source.attack_count += 1
        
        return True
    
    def _can_attack(self, source, target) -> bool:
        """检查是否可以攻击目标"""
        if source == target or target.dead:
            return False
        
        # 检查攻击次数限制
        max_attacks = 1 + source.extra_attack_count
        if source.attack_count >= max_attacks:
            return False
        
        # 检查距离
        distance = source.calculate_distance(target)
        attack_range = source.get_attack_range()
        
        return distance <= attack_range

class DefendCard(BasicCard):
    """闪牌"""
    def __init__(self, card_id: int, suit: str = "", number: int = 0):
        super().__init__(card_id, "闪", BASIC_DEFEND, suit, number)
    
    def use(self, game, source, target=None) -> bool:
        """使用闪牌"""
        # 闪牌通常在响应杀时使用
        return True

class HealCard(BasicCard):
    """桃牌"""
    def __init__(self, card_id: int, suit: str = "", number: int = 0):
        super().__init__(card_id, "桃", BASIC_HEAL, suit, number)
    
    def use(self, game, source, target=None) -> bool:
        """使用桃牌"""
        if target is None:
            target = source
        
        if target.health >= target.max_health:
            return False
        
        target.heal(1)
        return True

class NeutralizeCard(BasicCard):
    """酒牌"""
    def __init__(self, card_id: int, suit: str = "", number: int = 0):
        super().__init__(card_id, "酒", BASIC_NEUTRALIZE, suit, number)
    
    def use(self, game, source, target=None) -> bool:
        """使用酒牌"""
        if source.has_drunk:
            return False
        
        source.has_drunk = True
        return True

class EquipmentCard(Card):
    """装备牌基类"""
    def __init__(self, card_id: int, name: str, subtype: str, suit: str = "", number: int = 0):
        super().__init__(card_id, name, CARD_TYPE_EQUIPMENT, subtype, suit, number)
    
    def use(self, game, source, target=None) -> bool:
        """装备卡牌"""
        if target is not None and target != source:
            return False
        
        # 检查是否已有同类型装备
        old_equip = None
        for i, equip in enumerate(source.equipment_area):
            if equip.subtype == self.subtype:
                old_equip = equip
                break
        
        # 替换旧装备
        if old_equip:
            source.equipment_area.remove(old_equip)
            game.discard_pile.append(old_equip)
        
        # 装备新牌
        source.equipment_area.append(self)
        
        # 从手牌中移除
        if self in source.hand:
            source.hand.remove(self)
        
        return True

class WeaponCard(EquipmentCard):
    """武器牌"""
    def __init__(self, card_id: int, weapon_info: Dict, suit: str = "", number: int = 0):
        super().__init__(card_id, weapon_info["name"], EQUIP_WEAPON, suit, number)
        self.attack_range = weapon_info["range"]
        self.special_effect = weapon_info.get("effect", "")
        self.is_attack_horse = False
        self.is_defend_horse = False
        self.is_armor = False

class ArmorCard(EquipmentCard):
    """防具牌"""
    def __init__(self, card_id: int, armor_info: Dict, suit: str = "", number: int = 0):
        super().__init__(card_id, armor_info["name"], EQUIP_ARMOR, suit, number)
        self.effect = armor_info["effect"]
        self.is_attack_horse = False
        self.is_defend_horse = False
        self.is_armor = True

class MountCard(EquipmentCard):
    """坐骑牌"""
    def __init__(self, card_id: int, mount_info: Dict, subtype: str, suit: str = "", number: int = 0):
        super().__init__(card_id, mount_info["name"], subtype, suit, number)
        self.effect = mount_info["effect"]
        self.is_attack_horse = subtype == EQUIP_MOUNT_ATTACK
        self.is_defend_horse = subtype == EQUIP_MOUNT_DEFEND
        self.is_armor = False

class TrickCard(Card):
    """锦囊牌基类"""
    def __init__(self, card_id: int, name: str, subtype: str, suit: str = "", number: int = 0):
        super().__init__(card_id, name, CARD_TYPE_TRICK, subtype, suit, number)

class InstantTrickCard(TrickCard):
    """即时锦囊牌"""
    def __init__(self, card_id: int, name: str, specific_type: str, suit: str = "", number: int = 0):
        super().__init__(card_id, name, TRICK_INSTANT, suit, number)
        self.specific_type = specific_type

class DelayedTrickCard(TrickCard):
    """延时锦囊牌"""
    def __init__(self, card_id: int, name: str, specific_type: str, suit: str = "", number: int = 0):
        super().__init__(card_id, name, TRICK_DELAYED, suit, number)
        self.specific_type = specific_type
        self.turns_to_trigger = 2  # 大多数延时锦囊需要2回合后生效

# 武器信息
WEAPON_FAN = {"name": "方天画戟", "range": 4, "effect": "出牌阶段，可以对多个目标使用杀"}
WEAPON_SPEAR = {"name": "丈八蛇矛", "range": 3, "effect": "可以将两张手牌当作杀使用"}
WEAPON_SWORD = {"name": "青釭剑", "range": 2, "effect": "无视防具"}
WEAPON_BOW = {"name": "诸葛连弩", "range": 1, "effect": "出牌阶段可以无限使用杀"}
WEAPON_AXE = {"name": "青龙偃月刀", "range": 3, "effect": "杀被闪避后可以继续出杀"}

# 防具信息
ARMOR_LEATHER = {"name": "藤甲", "effect": "受到火焰伤害+1，其他伤害-1"}
ARMOR_MAIL = {"name": "仁王盾", "effect": "黑色杀无效"}
ARMOR_PLASTE = {"name": "八卦阵", "effect": "有50%几率闪避杀"}

# 坐骑信息
MOUNT_ATTACK_HORSE = {"name": "赤兔马", "effect": "攻击距离+1"}
MOUNT_DEFEND_HORSE = {"name": "的卢马", "effect": "其他角色计算与你的距离+1"}